package com.movisol.messengercommunicator.controllers;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.util.Date;

import android.content.Context;

import com.movisol.messengercommunicator.CommunicatorManager;
import com.movisol.messengercommunicator.data.CommunicatorRoot;
import com.movisol.messengercommunicator.data.CommunicatorUri;
import com.movisol.messengercommunicator.data.Conversation;
import com.movisol.messengercommunicator.data.ConversationCache;
import com.movisol.messengercommunicator.data.MessagesCache;
import com.movisol.messengercommunicator.ilisteners.IConversationsListLoaded;
import com.movisol.messengercommunicator.ilisteners.IMessagePosted;
import com.movisol.messengercommunicator.ilisteners.IMessagesListLoaded;



public class CommunicatorController{
	
	private static CommunicatorController INSTANCE = null;
	private CommunicatorManager comManager = null;
	private Context context;
	private ConversationCache conversationCache;
	private CommunicatorUri communicatorUri4Conversations;
	private CommunicatorUri communicatorUri4Messages;
	
	private CommunicatorRoot conversationsList;
	private CommunicatorRoot messagesList;
	
	private MessagesCache messagesCache;
	
	private CommunicatorRoot messageAnswered;
	
	
	//It does not allow to create a new instance of the class
	private CommunicatorController()
	{}

	
	public static CommunicatorController getInstance()
	{
		if( INSTANCE == null)
			INSTANCE =  new CommunicatorController();
		
		return INSTANCE;
	}
	
	
	//Blocks the clone method
	@Override
	protected Object clone() throws CloneNotSupportedException{
		throw new CloneNotSupportedException("Clone is not allowed");
	}
	
	
	public void initialize(Context context)
	{
		this.context = context;
		comManager = new CommunicatorManager(context);
	}
	
	public void getConversationCacheFromFile(String fileName) {
		
		FileInputStream fis = null;
		ObjectInputStream in = null;
		try {
			fis = context.openFileInput(fileName);
			 in = new ObjectInputStream(fis);
			// Recuperamos el objeto cache
			conversationCache = (ConversationCache) in.readObject();
		} catch (FileNotFoundException e) {
			conversationCache = null;
		} catch (StreamCorruptedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			
				try {
					if(in != null)
						in.close();
					if(fis != null)
						fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

		}
		
	}
	
	public void writeConversationUriToFile(String fileName) {

		FileOutputStream fos = null;
		ObjectOutputStream out = null;
		try {
			fos = context.openFileOutput(fileName,Context.MODE_PRIVATE);
			out = new ObjectOutputStream(fos);
			conversationCache = new ConversationCache(new Date(), communicatorUri4Conversations);
			out.writeObject(conversationCache);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				// Hay que cerrrar siempre los streams
				if (out != null)
					out.close();
				
				if (fos != null)
					fos.close();
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	public boolean isConversationUriCached() {

		if(conversationCache != null)
			return true;
		else
			return false;
	}
	
	public void getMessagesCacheFromFile(String conversationId) {
		
		FileInputStream fis = null;
		ObjectInputStream in = null;
		try {
			fis = context.openFileInput(conversationId);
			in = new ObjectInputStream(fis);
			// Recuperamos el objeto cache
			messagesCache = (MessagesCache) in.readObject();
		} catch (FileNotFoundException e) {
			messagesCache = null;
		} catch (StreamCorruptedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}catch (NullPointerException e) {
			messagesCache = null;
		}finally
		{
			try {
				if(in != null)
					in.close();
					
				if(fis != null)
					fis.close();
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
	}
	
	public void writeMessageUriToFile(String conversationId) {
		
		FileOutputStream fos = null;
		ObjectOutputStream out = null;
		try {
			fos = context.openFileOutput(conversationId,Context.MODE_PRIVATE);
			out = new ObjectOutputStream(fos);
			messagesCache = new MessagesCache(new Date(), communicatorUri4Messages, conversationId);
			out.writeObject(messagesCache);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				// Hay que cerrrar siempre los streams
				if (out != null)
					out.close();
				if (fos != null)
					fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	public boolean isMessagesUriCached() {
		if(messagesCache != null)
			return true;
		else
			return false;
	}
	
	public void updateConversationInConversationList(final String conversationId, final String lastMessage)
	{
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				synchronized(conversationsList)
				{
					int c = 0;
					if (conversationsList != null)
						for (Conversation conversation : conversationsList.getConversations())
						{
							if(conversation.getConversationId().equals(conversationId))
							{
								Conversation conver = null;
								try
								{
									conver = conversation.duplicate();
									conver.setLastMessage(lastMessage);
								}
								catch (CloneNotSupportedException e)
								{
									e.printStackTrace();
								}
								
								conversationsList.getConversations().remove(c);
								conversationsList.getConversations().add(0, conver);
								break;
							}
							c++;
						}
				}
			}
		}).start();
		
	}
	
	public String getConversationList(String userId, String signature) {
		return comManager.getConversationList(userId, signature);
	}
	
	public String getMessageList(String conversId) {
		return comManager.getMessageList(conversId);
	}
	
	public String getXMLfromUri(String uri) {
		return comManager.getXMLfromUri(uri);
	}

	public String postMessage(CommunicatorRoot cr, String userId) {
		return comManager.postMessage(cr, userId);
	}
	
	
	/******************ConversationListLoaded*****************/
	public void addConversationListLoadedListener(IConversationsListLoaded listener){
		if(comManager != null)
			comManager.addConversationListLoadedListener(listener);
	}
	
	
	public void removeConversationListLoadedListener(IConversationsListLoaded listener){
		if(comManager != null)
			comManager.removeConversationListLoadedListener(listener);
	}
	
	
	public void fireConversationsListLoaded(String error) {
		if(comManager != null)
			comManager.fireConversationsListLoaded(error);
	}
	/********************************************************/
	
	
	
	/******************MessagesListLoaded*****************/
	public void addMessagesListLoadedListener(IMessagesListLoaded listener){
		if(comManager != null)
			comManager.addMessagesListLoadedListener(listener);
	}
	
	
	public void removeMessagesListLoadedListener(IMessagesListLoaded listener){
		if(comManager != null)
			comManager.removeMessagesListLoadedListener(listener);
	}
	
	
	/**
	 * Fires all the Events for all the listener subscribed
	 */
	public void fireMessagesListLoaded(String error){
		if(comManager != null)
			comManager.fireMessagesListLoaded(error);
	}
	/********************************************************/
	
	
	
	/******************MessagePosted*****************/
	public void addMessagePostedListener(IMessagePosted listener){
		if(comManager != null)
			comManager.addMessagePostedListener(listener);
	}
	
	
	public void removeMessagePostedListener(IMessagePosted listener){
		if(comManager != null)
			comManager.removeMessagePostedListener(listener);
	}
	
	
	/**
	 * Fires all the Events for all the listener subscribed
	 */
	public void fireMessagePosted(String error){
		if(comManager != null)
			comManager.fireMessagePosted(error);
	}
	/********************************************************/
	
	
	
	public CommunicatorUri getCommunicatorUri4Conversations() {
		return communicatorUri4Conversations;
	}


	public void setCommunicatorUri4Conversations(CommunicatorUri communicatorUri4Conversations) {
		this.communicatorUri4Conversations = communicatorUri4Conversations;
	}


	public ConversationCache getConversationCache() {
		return conversationCache;
	}


	public void setConversationCache(ConversationCache conversationCache) {
		this.conversationCache = conversationCache;
	}

	public Context getContext() {
		return context;
	}
	
	public CommunicatorUri getCommunicatorUri4Messages() {
		return communicatorUri4Messages;
	}


	public void setCommunicatorUri4Messages(CommunicatorUri communicatorUri4Messages) {
		this.communicatorUri4Messages = communicatorUri4Messages;
	}


	public MessagesCache getMessagesCache() {
		return messagesCache;
	}


	public void setMessagesCache(MessagesCache messagesCache) {
		this.messagesCache = messagesCache;
	}
	
	public CommunicatorRoot getConversationsList() {
		return conversationsList;
	}


	public void setConversationsList(CommunicatorRoot conversationsList) {
		this.conversationsList = conversationsList;
	}


	public CommunicatorRoot getMessagesList() {
		return messagesList;
	}


	public void setMessagesList(CommunicatorRoot messagesList) {
		this.messagesList = messagesList;
	}


	public CommunicatorRoot getMessageAnswered() {
		return messageAnswered;
	}


	public void setMessageAnswered(CommunicatorRoot messageAnswered) {
		this.messageAnswered = messageAnswered;
	}

}
